%% 清空变量环境
close all;
clc,clear;
warning off;

%%  导入数据
res=readmatrix("sample_random_forest_data_chinese_varied_target.xlsx");
res1=res(801:end,1:end-1);%新预测数据
res=res(1:300,:);%样本数据
%% 数据归一化
X=res(:,1:end-1);
Y=res(:,end);
[x,psin]=mapminmax(X',0,1);
[y,pcout]=mapminmax(Y',0,1);

%% 划分数据集与测试集
num=size(res,1);% 总样本数
k=1;
if k==0
    statr=1:num;%不打乱样本
else
    statr=randperm(num);%打乱
end
r=0.9;%训练集比例
trainnum=floor(num*r);

xtrain=x(:,statr(1:trainnum));
ytrain=y(statr(1:trainnum));

xtest=x(:,statr(trainnum+1:end));
ytest=y(statr(trainnum+1:end));

%%训练模型
trees=1000;  %决策树个数
leaf=2;    %叶子数，过小会过拟合
wucha='on'; %打开误差图
importance='on';    %计算特征的重要性
net=TreeBagger(trees,xtrain',ytrain','OOBPredictorImportance',importance,'Method','regression','OOBPrediction',wucha,'minleaf',leaf);
import=net.OOBPermutedPredictorDeltaError; %重要性

%% 预测
re1=predict(net,xtrain');
re2=predict(net,xtest');
%实际预测值(反归一化)
Ytrain=Y(statr(1:trainnum));
Ytest=Y(statr(trainnum+1:end));

pre1=mapminmax('reverse',re1,pcout);
pre2=mapminmax('reverse',re2,pcout);

%% 均方根误差
error1=sqrt(mean((pre1-Ytrain).^2));
error2=sqrt(mean((pre2-Ytest).^2));

%% 相关指标计算
% R^2
R1=1-norm(Ytrain-pre1)^2/norm(Ytrain-mean(Ytrain))^2;
R2=1-norm(Ytest-pre2)^2/norm(Ytest-mean(Ytest))^2;

% MAE
mae1=mean(abs(Ytrain-pre1));
mae2=mean(abs(Ytest-pre2));

%% 新数据预测
newdata=res1;
newy=newpre(newdata,psin,pcout,net);
%保存数据
% xlswrite()

%% 画图
%误差图
figure
plot(1:trainnum,Ytrain,'r-^',1:trainnum,pre1,'b-*','LineWidth',1)
legend('真实值','预测值')
xlabel('样本点')
ylabel('预测值')
title('训练集预测结果对比')

figure
plot(1:num-trainnum,Ytest,'r-^',1:num-trainnum,pre2,'b-*','LineWidth',1)
legend('真实值','预测值')
xlabel('样本点')
ylabel('预测值')
title('测试集预测结果对比')

%百分比误差图
figure
plot((pre1-Ytrain)./Ytrain,'b-o','LineWidth',1)
legend('百分比误差')
xlabel('样本点')
ylabel('预测值')
title('训练集百分比误差曲线')

figure
plot((pre2-Ytest)./Ytest,'b-o','LineWidth',1)
legend('百分比误差')
xlabel('样本点')
ylabel('预测值')
title('测试集百分比误差曲线')

%拟合图
figure
plotregression(Ytrain,pre1,'训练集', ...
               Ytest,pre2,'测试集');
set(gcf,'Toolbar','figure');

%误差曲线
figure
plot(1:trees,oobError(net),'r--o','LineWidth',1)
legend('误差迭代曲线')
xlabel('决策树(迭代次数)')
ylabel('误差')
title('误差迭代曲线')

%特征重要性图
figure
bar(import,'green')
yticks([])
xlabel('特征')
ylabel('重要性')

%预测数据图
figure
plot(newy)
xlabel('样本点')
ylabel('预测值')



%% 预测函数
function y=newpre(newdata,psin,pcout,net)
    %归一化
    x=mapminmax('apply',newdata',psin);
    %预测
    y=predict(net,x');
    %反归一化
    y=mapminmax("reverse",y,pcout);
end

